package ${packagePrefix}.${domainObjectName?lower_case}.domain.model.aggregates;

import ${packagePrefix}.${domainObjectName?lower_case}.domain.model.entities.*;
import ${packagePrefix}.${domainObjectName?lower_case}.domain.model.valueobjects.*;
import ${packagePrefix}.common.domain.AggregateRoot;

import java.util.*;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

<#if generateComments>
/**
 * ${domainObjectName}聚合根
 * <p>
 * 聚合根是一个领域对象，它封装了一个相关对象的集合，确保整个聚合的一致性和完整性。
 * 外部对象仅能通过聚合根来访问聚合内的其他实体。聚合定义了一个清晰的业务边界。
 * </p>
 * 
 * @author Auto Generated
 */
</#if>
@Getter
@Slf4j
public class ${domainObjectName}Aggregate implements AggregateRoot<Long> {
    
    /**
     * 聚合根标识
     */
    private Long id;
    
    /**
     * ${domainObjectName}名称
     */
    private String name;
    
<#list fields as field>
    <#if field.name != "id" && field.name != "name" && field.name != "createdTime" && field.name != "updatedTime" && field.name != "createdBy" && field.name != "updatedBy" && field.name != "isDeleted">
    /**
     * ${field.comment}
     */
    private ${field.javaType} ${field.name};
    </#if>
</#list>
    
    /**
     * 聚合内部实体集合
     * 示例: 如果${domainObjectName}包含多个子实体项，可在此管理
     */
    private List<${domainObjectName}Item> items = new ArrayList<>();
    
    /**
     * 版本号 - 用于乐观锁控制
     */
    private Long version;

    // 私有构造函数，通过静态工厂方法创建实例
    private ${domainObjectName}Aggregate() {}
    
    /**
     * 创建新的${domainObjectName}聚合
     * 
     * @param name ${domainObjectName}名称
     * @return ${domainObjectName}聚合实例
     */
    public static ${domainObjectName}Aggregate create(String name) {
        ${domainObjectName}Aggregate aggregate = new ${domainObjectName}Aggregate();
        aggregate.name = name;
        // 设置初始状态和默认值
        <#if hasStatusField>
        aggregate.status = 0; // 初始状态
        </#if>
        aggregate.items = new ArrayList<>();
        
        // 领域事件：聚合创建
        log.info("${domainObjectName}聚合创建: {}", name);
        
        return aggregate;
    }
    
    /**
     * 添加聚合内部实体项
     * 
     * @param item 实体项
     * @return 当前聚合对象(链式调用)
     */
    public ${domainObjectName}Aggregate addItem(${domainObjectName}Item item) {
        // 领域规则验证
        validateItem(item);
        
        // 添加并维护聚合完整性
        items.add(item);
        
        return this;
    }
    
    /**
     * 移除聚合内部实体项
     * 
     * @param itemId 实体项ID
     * @return 当前聚合对象(链式调用)
     */
    public ${domainObjectName}Aggregate removeItem(Long itemId) {
        // 领域规则：确保实体存在
        items.removeIf(item -> item.getId().equals(itemId));
        return this;
    }
    
    /**
     * 更新${domainObjectName}基本信息
     * 
     * @param name 新名称
     <#list fields as field>
     <#if field.name != "id" && field.name != "name" && field.name != "createdTime" && field.name != "updatedTime" && field.name != "createdBy" && field.name != "updatedBy" && field.name != "isDeleted" && field.name != "items" && field.name != "version">
     * @param ${field.name} ${field.comment}
     </#if>
     </#list>
     * @return 当前聚合对象(链式调用)
     */
    public ${domainObjectName}Aggregate update(String name<#list fields as field><#if field.name != "id" && field.name != "name" && field.name != "createdTime" && field.name != "updatedTime" && field.name != "createdBy" && field.name != "updatedBy" && field.name != "isDeleted" && field.name != "items" && field.name != "version">, ${field.javaType} ${field.name}</#if></#list>) {
        // 验证领域规则
        validateUpdate(name);
        
        // 更新聚合数据
        this.name = name;
        <#list fields as field>
        <#if field.name != "id" && field.name != "name" && field.name != "createdTime" && field.name != "updatedTime" && field.name != "createdBy" && field.name != "updatedBy" && field.name != "isDeleted" && field.name != "items" && field.name != "version">
        this.${field.name} = ${field.name};
        </#if>
        </#list>
        
        return this;
    }
    
    <#if hasStatusField>
    /**
     * 变更状态
     * 
     * @param newStatus 新状态
     * @return 当前聚合对象(链式调用)
     */
    public ${domainObjectName}Aggregate changeStatus(Integer newStatus) {
        // 领域规则：状态流转验证
        validateStatusChange(this.status, newStatus);
        
        this.status = newStatus;
        
        // 可能触发的领域事件
        if (newStatus == 1) {
            log.info("${domainObjectName}已启用: {}", this.id);
        } else if (newStatus == 0) {
            log.info("${domainObjectName}已禁用: {}", this.id);
        }
        
        return this;
    }
    
    /**
     * 验证状态变更合法性
     */
    private void validateStatusChange(Integer oldStatus, Integer newStatus) {
        // 领域规则：状态流转规则
        // 例如: 只有状态为0的才能设置为1，状态为1的才能设置为0
        if (oldStatus.equals(newStatus)) {
            return; // 状态相同，无需变更
        }
        
        // 示例规则：只允许0->1, 1->0的状态变更
        boolean isValidChange = (oldStatus == 0 && newStatus == 1) || 
                                (oldStatus == 1 && newStatus == 0);
        
        if (!isValidChange) {
            throw new IllegalStateException("不允许从状态" + oldStatus + "变更为状态" + newStatus);
        }
    }
    </#if>
    
    /**
     * 验证实体项合法性
     */
    private void validateItem(${domainObjectName}Item item) {
        // 领域规则：验证实体项的有效性
        if (item == null) {
            throw new IllegalArgumentException("实体项不能为空");
        }
        
        // 领域规则：验证没有重复项
        boolean duplicated = items.stream()
            .anyMatch(existingItem -> existingItem.getName().equals(item.getName()));
            
        if (duplicated) {
            throw new IllegalArgumentException("已存在相同名称的实体项: " + item.getName());
        }
    }
    
    /**
     * 验证更新操作的合法性
     */
    private void validateUpdate(String name) {
        // 领域规则：名称不能为空
        if (name == null || name.trim().isEmpty()) {
            throw new IllegalArgumentException("${domainObjectName}名称不能为空");
        }
        
        <#if specialRequirements?? && specialRequirements?contains("审批")>
        // 领域规则：审批中的数据不允许修改
        if (this.status != null && this.status == 2) { // 假设2表示审批中状态
            throw new IllegalStateException("${domainObjectName}处于审批中状态，不允许修改");
        }
        </#if>
    }
    
    /**
     * 从聚合根派生仓储对象
     * 
     * @return 数据对象
     */
    public ${domainObjectName}DO toDataObject() {
        ${domainObjectName}DO dataObject = new ${domainObjectName}DO();
        dataObject.setId(this.id);
        dataObject.setName(this.name);
        <#list fields as field>
        <#if field.name != "id" && field.name != "name" && field.name != "createdTime" && field.name != "updatedTime" && field.name != "createdBy" && field.name != "updatedBy" && field.name != "isDeleted" && field.name != "items" && field.name != "version">
        dataObject.set${field.name?cap_first}(this.${field.name});
        </#if>
        </#list>
        dataObject.setVersion(this.version);
        return dataObject;
    }
    
    /**
     * 从数据对象还原聚合根
     * 
     * @param dataObject 数据对象
     * @return 聚合根对象
     */
    public static ${domainObjectName}Aggregate fromDataObject(${domainObjectName}DO dataObject) {
        ${domainObjectName}Aggregate aggregate = new ${domainObjectName}Aggregate();
        aggregate.id = dataObject.getId();
        aggregate.name = dataObject.getName();
        <#list fields as field>
        <#if field.name != "id" && field.name != "name" && field.name != "createdTime" && field.name != "updatedTime" && field.name != "createdBy" && field.name != "updatedBy" && field.name != "isDeleted" && field.name != "items" && field.name != "version">
        aggregate.${field.name} = dataObject.get${field.name?cap_first}();
        </#if>
        </#list>
        aggregate.version = dataObject.getVersion();
        
        // 加载聚合内的实体集合(这里只是示例，实际可能需要从别的表加载)
        // 例如：aggregate.items = itemRepository.findBy${domainObjectName}Id(aggregate.id);
        
        return aggregate;
    }
    
    @Override
    public Long getAggregateId() {
        return this.id;
    }
} 